<template>
  <div
    :class="[
      'anov-part',
      'vdr',
      anovPart.className,
      enabled ? 'anov-vdr-border' : '',
      auxiliary ? 'auxiliary-line' : '',
      analogData ? 'water-mark' : ''
    ]"
    :id="anovPart.id"
    ref="anovPart"
    :style="{ ...style, borderColor: auxiliaryColor }"
    @mousedown="elementMouseDown"
    @touchstart="elementTouchDown"
    @dblclick="focus"
  >
    <component
      :is="anovPart.component"
      :key="anovPartKey"
      v-bind="anovPart.params"
      :params="anovPart.params"
    ></component>
    <div
      v-for="handle in actualHandles"
      :key="handle"
      :class="['handle', 'handle' + '-' + handle]"
      :style="{ display: enabled ? 'block' : 'none' }"
      @mousedown.stop.prevent="handleDown(handle, $event)"
      @touchstart.stop.prevent="handleTouchDown(handle, $event)"
    ></div>
    <span class="anovPart-delete" v-if="enabled" @click="destroy">x</span>
  </div>
</template>
<script>
import { requireComponent, getKey } from './utils/vueFiles'
import './mixins/vdr.css'
import vdr from './mixins/vdr'
import Vue from 'vue'
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState('focus', ['isOpen']),
    ...mapState(['page', 'dataSet']),
    ...mapState('env', ['designSize']),
    ...mapState('part', ['auxiliary', 'auxiliaryColor'])
  },
  props: {
    part: {
      type: Object,
      required: true,
      default: () => {}
    },
    anovFile: {
      required: true,
      type: String,
      default: ''
    }
  },
  data() {
    return {
      anovPartKey: 0,
      analogData: false,
      anovPart: {
        id: this.part?.id,
        component: this.part?.component || `./comps/${this.part?.id}.vue`,
        className: this.part?.className,
        params: this.part?.params || {},
        hasFocus: this.part.hasFocus === false ? false : true,
        style: {
          width: '300px',
          height: '300px',
          ...(this.part?.style || {})
        }
      }
    }
  },
  created() {
    // 注册组件
    this.registerComps()
    this.registerFocus()
    // 添加模拟数据底纹标示
    if (app.config.analogData !== false) {
      this.analogData = this.dataSet[this.anovPart.id]?.analogData
    }
  },
  mounted() {
    app.log(`appPart-${this.anovPart.id}-mounted`)
  },
  watch: {
    designSize: {
      handler: function () {
        this.checkParentSize()
      },
      deep: true
    }
  },
  methods: {
    //组件初始化
    init() {
      // app.log(`appPart-${this.anovPart.id}-init`)
      let tl
      try {
        tl = this.getTl()
      } catch (e) {
        console.error(e)
      }
      const flag = tl instanceof TimelineLite || tl instanceof TweenLite
      flag && !tl.vars.id && (tl.vars.id = this.anovPart.id)
      return tl
    },
    // 组件更新
    update(domUpdate = true) {
      this.reset('update', domUpdate)
    },
    // 组件重置
    reset(type = 'init', domUpdate = true) {
      if (type == 'update' && domUpdate == false) {
        let childComponent = this.$children[0]
        childComponent[type] && childComponent[type]()
        return
      }
      this.anovPartKey++
      this.$nextTick(() => {
        let id = this.anovPart.id
        let childComponent = this.$children[0]
        let tls = app.animateServer.getCurrentRouteTl('enter')
        let labelsArray = tls.getLabelsArray()
        let label = labelsArray.find((label) => label.name == id)
        let oldTl = tls.getChildren(false).find((v) => v.vars.id == id)
        let oldTlStartTime = label?.time || oldTl?.startTime()
        let newTl, flag
        tls.remove(oldTl)
        oldTl?.clear()
        oldTl = null
        if (childComponent[type]) {
          newTl = childComponent[type]()
        } else {
          newTl = this.getTl()
        }
        if (newTl instanceof TimelineLite || newTl instanceof TweenLite) {
          newTl.vars.id = id
          newTl.eventCallback('onComplete', () => {
            !flag && tls.add(newTl, oldTlStartTime)
            flag = true
          })
        }
      })
    },
    // 组件销毁
    destroy() {
      app.anovPage.deletePart(this.anovPart.id)
      app.$emit('anovPartChange', this.page)
    },
    // 获取子动画线
    getTl() {
      let childComponent = this.$children[0]
      if (childComponent.init) {
        let tl = childComponent.init()
        return tl
      } else {
        app.log(
          `${childComponent.$options._componentTag} init method is not set`
        )
      }
    },
    // 删除动画线
    removeTl(id = this.anovPart.id) {
      let tls = app.animateServer.getCurrentRouteTl('enter')
      let oldTl = tls.getChildren(false).find((v) => v.vars.id == id)
      tls.remove(oldTl)
      oldTl?.clear()
      oldTl = null
    },
    // 注册组件
    registerComps() {
      if (!this.anovPart.component) return
      const regRuls = [
        {
          rule: /^(\.|\.\.)\/.*[\w-]+\.vue$/,
          type: 'relativeSrc' //相对路径
        },
        {
          rule: /^[0-9a-zA-z_-]+$/, //修改正则匹配规则
          type: 'comp' //已注册组件
        },
        {
          rule: /^htt(p|ps):\/\/.*[\w-]+\.vue$/,
          type: 'remoteComp' //远程.vue文件
        }
      ]
      for (let i = 0; i < regRuls.length; i++) {
        let item = regRuls[i]
        if (item.rule.test(this.anovPart.component)) {
          this.anovPart.type = item.type
          break
        }
      }
      switch (this.anovPart.type) {
        case 'relativeSrc':
          let relativeSrc =
            this.anovFile.replace(/^src/, '.').replace(/[\w-]+\.vue$/, '') +
            this.anovPart.component.replace(/^\.\//, '')
          const componentSrc = getKey(relativeSrc)
          const childrenComponent = requireComponent(componentSrc).default
          Vue.component(this.anovPart.id, childrenComponent)
          this.anovPart.component = this.anovPart.id
          break
        case 'comp':
          //todo?
          break
        case 'remoteComp':
          //todo?
          break
      }
      this.$options.name = this.anovPart.id
      app.anovPart[this.anovPart.id] = this
    },
    registerFocus() {
      if (!this.anovPart.hasFocus) return
      app.focusServer.setFocusOptions({
        id: `${this.$route.name}.${this.anovPart.id}`
      })
    },
    focus() {
      if (!this.isOpen || !this.anovPart.hasFocus) return
      app.focusServer.activated(`${this.$route.name}.${this.anovPart.id}`)
    }
  },
  beforeDestroy() {},
  mixins: [vdr]
}
</script>
<style lang="scss" scoped>
.anov-part {
  position: absolute;
  box-sizing: border-box;
}
.auxiliary-line {
  border: 1px solid red;
}
.water-mark {
  &:before {
    position: absolute;
    z-index: -10;
    content: '模拟数据模拟数据';
    line-height: 2.5;
    letter-spacing: 10px;
    font-size: 26px;
    left: 50%;
    top: 50%;
    transform: translateX(-50%) translateY(-50%) rotate(-45deg);
    transform-origin: center;
    color: rgba(193, 255, 251, 0.6);
    overflow: hidden;
    max-width: 170px;
    max-height: 50%;
  }
}
.anovPart-delete {
  box-sizing: border-box;
  position: absolute;
  width: 15px;
  height: 15px;
  background: rgba(0, 190, 255, 0.1);
  border: 1px solid #4f6161;
  top: -7px;
  right: -7px;
  border-radius: 2px;
  cursor: pointer;
  line-height: 11px;
  text-align: center;
  color: rgba(0, 190, 255, 0.5);
  transition: border-color, color, transform 0.5s ease-in-out;
  &:hover {
    color: rgba(0, 190, 255, 1);
    border-color: rgba(0, 190, 255, 1);
    transform: scale(2);
  }
}
</style>
